﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Windows.Forms;

namespace belov_test
{
    class InfoSerializer
    {
        public static void SaveUsersInfo(List<UserInfo> usersInfo)
        {
            SaveUsersInfo(usersInfo, true);
        }

        public static void SaveUsersInfo(List<UserInfo> usersInfo, bool updateToCurrentDate)
        {
            XmlTextWriter xmlWriter = new XmlTextWriter(AuthorizationForm.USERS_DATA_FILE_PATH, Encoding.UTF8);
            xmlWriter.Formatting = Formatting.Indented;
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("users");
            xmlWriter.WriteFullEndElement();
            xmlWriter.Close();

            XmlDocument usersXml = new XmlDocument();
            usersXml.Load(AuthorizationForm.USERS_DATA_FILE_PATH);

            for (int i = 0; i < usersInfo.Count; i++)
            {
                UserInfo currentUserInfo = usersInfo[i];

                XmlElement newUserInfo = usersXml.CreateElement("user");

                newUserInfo.SetAttribute("name", currentUserInfo.Name);
                newUserInfo.SetAttribute("surname", currentUserInfo.Surname);
                newUserInfo.SetAttribute("patronymic", currentUserInfo.Patronymic);
                newUserInfo.SetAttribute("guid", currentUserInfo.Guid.ToString());

                

                usersXml.GetElementsByTagName("users")[0].AppendChild(newUserInfo);

                SaveUserInfo(currentUserInfo, updateToCurrentDate);
            }

            usersXml.Save(AuthorizationForm.USERS_DATA_FILE_PATH);
        }

        public static void SaveUserInfo(UserInfo userInfo)
        {
            SaveUserInfo(userInfo, true);
        }

        public static void SaveUserInfo(UserInfo userInfo, bool updateToCurrentDate)
        {
            if (userInfo != null)
            {
                string filePath = GetUserFilePath(userInfo.Guid.ToString());

                XmlTextWriter xmlWriter = new XmlTextWriter(filePath, Encoding.UTF8);

                xmlWriter.Formatting = Formatting.Indented;

                xmlWriter.WriteStartDocument();
                xmlWriter.WriteStartElement("userInfo");

                xmlWriter.WriteStartElement("user");
                xmlWriter.WriteAttributeString("guid", userInfo.Guid.ToString());
                xmlWriter.WriteAttributeString("lastAccUsing", updateToCurrentDate ? GetCurrentDateAndTime() : userInfo.LastAccountUsing);
                xmlWriter.WriteEndElement();

                xmlWriter.WriteStartElement("testsResults");

                for (int i = 0; i < userInfo.GetTestResultsCount(); i++)
                {
                    TestResult testResult = userInfo.GetTestResult(i);

                    xmlWriter.WriteStartElement("test");
                    xmlWriter.WriteAttributeString("testTime", testResult.Time.ToString());
                    xmlWriter.WriteAttributeString("beginTime", testResult.BeginTime);
                    xmlWriter.WriteAttributeString("endTime", testResult.EndTime);
                    xmlWriter.WriteAttributeString("choleric", testResult.cholericPercent.ToString());
                    xmlWriter.WriteAttributeString("sanguine", testResult.sanguinePercent.ToString());
                    xmlWriter.WriteAttributeString("phlegmatic", testResult.phlegmaticPercent.ToString());
                    xmlWriter.WriteAttributeString("melancholiac", testResult.melancholiacPercent.ToString());

                    xmlWriter.WriteEndElement();
                }

                xmlWriter.WriteEndElement();

                xmlWriter.WriteFullEndElement();

                xmlWriter.Close();
            }
        }

        public static String GetUserFilePath(String guid)
        {
            return AuthorizationForm.USERS_DATA_DIRECTORY_PATH + "\\" + guid + ".xml";
        }

        public static List<AdminInfo> LoadAdminsInfo()
        {
            List<AdminInfo> admins = new List<AdminInfo>();

            if (!File.Exists(AuthorizationForm.ADMINS_DATA_FILE_PATH))
            {
                MessageBox.Show("Не найден файл с администраторами!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            try
            {
                XmlDocument adminsXml = new XmlDocument();
                adminsXml.Load(AuthorizationForm.ADMINS_DATA_FILE_PATH);

                XmlNodeList adminNodes = adminsXml.GetElementsByTagName("admin"); ;

                for (int i = 0; i < adminNodes.Count; i++)
                {
                    XmlAttributeCollection adminNodeAttributes = adminNodes[i].Attributes;

                    AdminInfo adminInfo = new AdminInfo();

                    for (int j = 0; j < adminNodeAttributes.Count; j++)
                    {
                        switch (adminNodeAttributes[j].Name)
                        {
                            case "login":
                                {
                                    adminInfo.Login = adminNodeAttributes[j].Value;
                                    break;
                                }
                            case "password":
                                {
                                    adminInfo.Password = adminNodeAttributes[j].Value;
                                    break;
                                }
                        }
                    }
                    admins.Add(adminInfo);
                }

            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Ошибка загрузки файла с администраторами! " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            return admins;
        }

        public static void SaveAminsInfo(List<AdminInfo> admins)
        {
            XmlTextWriter xmlWriter = new XmlTextWriter(AuthorizationForm.ADMINS_DATA_FILE_PATH, Encoding.UTF8);
            xmlWriter.Formatting = Formatting.Indented;
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("admins");
            xmlWriter.WriteFullEndElement();
            xmlWriter.Close();

            XmlDocument adminsXml = new XmlDocument();
            adminsXml.Load(AuthorizationForm.ADMINS_DATA_FILE_PATH);

            for (int i = 0; i < admins.Count; i++)
            {
                AdminInfo currentAdminInfo = admins[i];

                XmlElement newAdminInfo = adminsXml.CreateElement("admin");

                newAdminInfo.SetAttribute("login", currentAdminInfo.Login);
                newAdminInfo.SetAttribute("password", currentAdminInfo.Password);

                adminsXml.GetElementsByTagName("admins")[0].AppendChild(newAdminInfo);
            }

            adminsXml.Save(AuthorizationForm.ADMINS_DATA_FILE_PATH);
        }

        public static List<UserInfo> LoadUsersInfo()
        {
            List<UserInfo> users = new List<UserInfo>();

            if (!File.Exists(AuthorizationForm.USERS_DATA_FILE_PATH))
            {
                MessageBox.Show("Не найден файл с пользователями!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            try
            {
                XmlDocument usersXml = new XmlDocument();
                usersXml.Load(AuthorizationForm.USERS_DATA_FILE_PATH);

                XmlNodeList userNodes = usersXml.GetElementsByTagName("users")[0].ChildNodes;

                for (int i = 0; i < userNodes.Count; i++)
                {
                    XmlAttributeCollection userNodeAttributes = userNodes[i].Attributes;

                    UserInfo userInfo = new UserInfo();

                    for (int j = 0; j < userNodeAttributes.Count; j++)
                    {
                        switch (userNodeAttributes[j].Name)
                        {
                            case "name":
                                {
                                    userInfo.Name = userNodeAttributes[j].Value;
                                    break;
                                }
                            case "patronymic":
                                {
                                    userInfo.Patronymic = userNodeAttributes[j].Value;
                                    break;
                                }
                            case "surname":
                                {
                                    userInfo.Surname = userNodeAttributes[j].Value;
                                    break;
                                }
                            case "guid":
                                {
                                    userInfo.Guid = new Guid(userNodeAttributes[j].Value);
                                    break;
                                }
                        }
                    }
                    LoadUserTestResults(userInfo);
                    users.Add(userInfo);
                }

            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Ошибка загрузки файла с пользователями! " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            return users;
        }

        private static void LoadUserTestResults(UserInfo userInfo)
        {
            String filePath = GetUserFilePath(userInfo.Guid.ToString());

            if (!File.Exists(filePath))
            {
                MessageBox.Show("Не найден файл \"" + filePath + "\"!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<TestResult> testResults = new List<TestResult>();

            try
            {
                XmlDocument usersXml = new XmlDocument();
                usersXml.Load(filePath);

                XmlAttributeCollection userAttrs = usersXml.GetElementsByTagName("user")[0].Attributes;

                for (int i = 0; i < userAttrs.Count; i++)
                {
                    if (userAttrs[i].Name == "lastAccUsing")
                    {
                        userInfo.LastAccountUsing = userAttrs[i].Value;
                    }
                }

                XmlNodeList testsInfoList = usersXml.GetElementsByTagName("test");

                for (int i = 0; i < testsInfoList.Count; i++)
                {
                    TestResult testResult = new TestResult();
                    XmlAttributeCollection testInfoAttributes = testsInfoList[i].Attributes;

                    for (int j = 0; j < testInfoAttributes.Count; j++)
                    {
                        switch (testInfoAttributes[j].Name)
                        {
                            case "choleric":
                                {
                                    testResult.cholericPercent = Convert.ToInt32(testInfoAttributes[j].Value);
                                    break;
                                }
                            case "sanguine":
                                {
                                    testResult.sanguinePercent = Convert.ToInt32(testInfoAttributes[j].Value);
                                    break;
                                }
                            case "phlegmatic":
                                {
                                    testResult.phlegmaticPercent = Convert.ToInt32(testInfoAttributes[j].Value);
                                    break;
                                }
                            case "melancholiac":
                                {
                                    testResult.melancholiacPercent = Convert.ToInt32(testInfoAttributes[j].Value);
                                    break;
                                }
                            case "testTime":
                                {
                                    testResult.Time = Convert.ToInt32(testInfoAttributes[j].Value);
                                    break;
                                }
                            case "beginTime":
                                {
                                    testResult.BeginTime = testInfoAttributes[j].Value;
                                    break;
                                }
                            case "endTime":
                                {
                                    testResult.EndTime = testInfoAttributes[j].Value;
                                    break;
                                }
                        }
                    }
                    userInfo.AddTestResult(testResult);
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Ошибка загрузки файла \"" + filePath + "\"! " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        public static DateTime GetCurrentTimestamp()
        {
            return DateTime.Now;
        }
        
        public static string GetCurrentDate()
        {
            string day = GetNormalizedDateElement(DateTime.Now.Day.ToString());
            string month = GetNormalizedDateElement(DateTime.Now.Month.ToString());

            return day + "." + month + "." + DateTime.Now.Year;
        }

        public static string GetCurrentTime()
        {
            string hour = GetNormalizedDateElement(DateTime.Now.Hour.ToString());
            string minute = GetNormalizedDateElement(DateTime.Now.Minute.ToString());

            return hour + ":" + minute;
        }

        public static string GetCurrentDateAndTime()
        {
            return GetCurrentDate() + " " + GetCurrentTime();
        }

        private static string GetNormalizedDateElement(string element)
        {
            if (element.Length == 1)
            {
                return "0" + element;
            }

            return element;
        }

        public static UserInfo InitNewUserInfo(UserInfo userInfo)
        {
            userInfo.LastAccountUsing = "Используется впервые";
            return userInfo;
        }

        private static TestResult CreateEmptyTestResult()
        {
            TestResult testResult = new TestResult();

            return testResult;
        }

        public static UserInfo InitUserInfoFromFile(string filePath, UserInfo userInfo)
        {
            XmlDocument xmlDocument = new XmlDocument();

            xmlDocument.Load(filePath);
            XmlNodeList userNodes = xmlDocument.GetElementsByTagName("user");

            if (userNodes.Count > 0)
            {
                XmlNode userNode = userNodes[0];
                XmlAttributeCollection userNodeAttributes = userNode.Attributes;

                for (int i = 0; i < userNodeAttributes.Count; i++)
                {
                    switch (userNodeAttributes[i].Name)
                    {
                        case "lastAccUsing":
                            {
                                userInfo.LastAccountUsing = userNodeAttributes[i].Value;
                                break;
                            }
                    }
                }

                XmlNodeList testNodesList = xmlDocument.GetElementsByTagName("test");
                int passedTestNum = 0;

                for (int i = 0; i < testNodesList.Count; i++)
                {
                    XmlAttributeCollection testNodeAttributes = testNodesList[i].Attributes;
                    TestResult testResult = new TestResult();

                    for (int j = 0; j < testNodeAttributes.Count; j++)
                    {
                        switch (testNodeAttributes[j].Name)
                        {
                            case "choleric":
                                {
                                    testResult.cholericPercent = Convert.ToInt32(testNodeAttributes[j].Value);
                                    break;
                                }
                            case "sanguine":
                                {
                                    testResult.sanguinePercent = Convert.ToInt32(testNodeAttributes[j].Value);
                                    break;
                                }
                            case "phlegmatic":
                                {
                                    testResult.phlegmaticPercent = Convert.ToInt32(testNodeAttributes[j].Value);
                                    break;
                                }
                            case "melancholiac":
                                {
                                    testResult.melancholiacPercent = Convert.ToInt32(testNodeAttributes[j].Value);
                                    break;
                                }
                            case "testTime":
                                {
                                    testResult.Time = Convert.ToInt32(testNodeAttributes[j].Value);
                                    break;
                                }
                            case "beginTime":
                                {
                                    testResult.BeginTime = testNodeAttributes[j].Value;
                                    break;
                                }
                            case "endTime":
                                {
                                    testResult.EndTime = testNodeAttributes[j].Value;
                                    break;
                                }
                        }
                    }

                    userInfo.AddTestResult(testResult);
                    userInfo.PassedTests = passedTestNum;
                }
            }

            return userInfo;
        }
    }
}
